package com.liuwa.openapi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.liuwa.common.exception.NotExistException;
import com.liuwa.common.exception.SimpleException;
import com.liuwa.common.utils.DateUtils;
import com.liuwa.common.utils.UserUtils;
import com.liuwa.framework.security.authens.OauthAccessToken;
import com.liuwa.framework.web.service.TokenService;
import com.liuwa.knowledge.domain.User;
import com.liuwa.knowledge.service.UserService;
import com.liuwa.openapi.service.OpenapiTokenService;
import com.liuwa.social.config.SocialPlatform;
import com.liuwa.social.http.WeixinHttpClient;
import com.liuwa.social.weixin.aes.WXBizMsgCrypt;
import com.liuwa.social.weixin.utils.WeixinUtils;
import com.liuwa.social.weixin.vo.AccessToken;
import com.liuwa.social.weixin.weapp.model.WeappLoginInfo;
import com.liuwa.social.weixin.weapp.model.WeappSession;
import com.liuwa.social.weixin.weapp.model.WeappUserInfo;
import com.liuwa.social.weixin.weapp.util.AES;
import com.liuwa.social.weixin.weapp.util.WeappUtil;
import com.liuwa.sys.domain.Oauth;
import com.liuwa.sys.service.OauthService;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.client.ClientProtocolException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;


/**
 * 微信小程序
 * @author rubekid
 *
 * 2017年8月23日 下午11:49:17
 */
@RestController
@RequestMapping(value= "/openapi/weapp")
public class OpenapiWeappController {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private OauthService oauthService;

	@Autowired
	private OpenapiTokenService openapiTokenService;

	@Autowired
	private UserService userService;

	/**
	 *  小程序-开发者ID
	 */
	@Value("${social.weapp.app_id}")
	private String appId;

	/**
	 * 小程序-开发者密码
	 */
	@Value("${social.weapp.app_secret}")
	private String appSecret;


	/**
	 * 小程序-消息推送-token
	 */
	@Value("${social.weapp.token:}")
	private String token;

	/**
	 * 小程序-消息推送-消息加密密钥
	 */
	@Value("${social.weapp.encoding_aes_key:}")
	private String encodingAesKey;

	/**
	 * 小程序-消息推送-消息加密密钥
	 */
	@Value("${social.weapp.data_format:'JSON'}")
	private String dataFormat;






	/**
	 * 获取session
	 * @param code
	 * @return
	 */
	@RequestMapping(value = "/session/{code}", method = RequestMethod.GET)
	@ResponseBody
	public WeappSession getSession(@PathVariable("code") String code){
		WeappSession session = WeappUtil.getSessionByCode(code);
		return session;
	}

	/**
	 * 小程序登录
	 * @param loginInfo
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public OauthAccessToken login(@RequestBody WeappLoginInfo loginInfo) throws ClientProtocolException, IOException {
		WeappSession session = WeappUtil.getSessionByCode(loginInfo.getCode());
		logger.info(JSON.toJSONString(session));
		String openId = session.getOpenid();
		Oauth oauth = oauthService.findByOpenId(SocialPlatform.WEAPP, openId);
		WeappUserInfo weappUserInfo = null;
		User user = null;
		if(oauth == null){
			if(loginInfo.getUserData() != null){
				weappUserInfo = WeappUtil.getUserInfo(loginInfo.getUserData(), session.getSessionKey());
				if(weappUserInfo == null){
					throw new SimpleException("获取微信用户信息失败");
				}
			}

			user = userService.authRegister(openId, SocialPlatform.WEAPP);
		}
		else{
			user = userService.get(oauth.getUserId());
		}

		return  openapiTokenService.generate(user);
	}

	/**
	 * 数据解密
	 * @param encryptedData
	 * @param iv
	 * @param code
	 * @return
	 */
	@RequestMapping(value = "/decrypt", method = RequestMethod.GET)
	public JSONObject decodeUserInfo(@RequestParam(value = "encryptedData") String encryptedData,
									 @RequestParam(value = "iv") String iv,
									 @RequestParam(value = "code") String code){

		WeappSession session = WeappUtil.getSessionByCode(code);

		if(null == session){
			throw new SimpleException("获取session失败");
		}

		String sessionKey = session.getSessionKey();

		try {
			AES aes = new AES();
			byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
			if(null != resultByte && resultByte.length > 0){
				String str = new String(resultByte, "UTF-8");
				return JSONObject.parseObject(str);
			}
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		throw new SimpleException("解密失败");
	}


	/**
	 * 消息推送
	 * @param signature
	 * @param timestamp
	 * @param nonce
	 * @param echostr
	 * @param postData
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/pusher")
	public void pusher(@RequestParam(value = "signature", required = false) String signature,
					   @RequestParam(value = "timestamp", required = false) String timestamp,
					   @RequestParam(value = "nonce", required = false) String nonce,
					   @RequestParam(value = "echostr", required = false) String echostr,
					   @RequestBody(required = false) String postData,
					   HttpServletRequest request,
					   HttpServletResponse response)throws Exception {

		Map<String, String> map = new HashMap<String, String>();
		Enumeration<String> e = request.getParameterNames();
		while(e.hasMoreElements()){
			String name = e.nextElement();
			String value =  request.getParameter(name);
			map.put(name, value);
		}
		WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, WeappUtil.APP_ID);
		pc.verifyUrl(signature, timestamp, nonce, echostr);
		if(echostr != null){
			response.getWriter().print(echostr);

		}
		else{
			String encryptType = map.get("encrypt_type");
			JSONObject body = JSONObject.parseObject(postData);
			if("aes".equalsIgnoreCase(encryptType)){
				String result = pc.decryptMsg(signature, timestamp, nonce, postData, dataFormat);
				body = JSONObject.parseObject(result);
			}

			logger.info("====== 推送消息内容 =======\n" + body.toString());

			String fromUserName = body.getString("FromUserName");
			String toUserName = body.getString("ToUserName");
			String msgType = body.getString("MsgType");
			if("event".equalsIgnoreCase(msgType)) {
				if("user_enter_tempsession".equals(body.getString("Event"))
						&& body.containsKey("SessionFrom")){
					String commandCode = body.getString("SessionFrom");
					handlerCommand(commandCode, fromUserName);
					return ;
				}
				else if("kf_create_session".equals(body.getString("Event"))){
					// TODO
					return ;
				}
				else if("kf_close_session".equals(body.getString("Event"))){
					return ;
				}

				// /pages/anchor/index?id=11232
			}
			else if("text".equalsIgnoreCase(msgType)){
				String content = body.getString("Content").trim();
				String regex = "^[^#]*(#\\w+#)[^#]*$";
				if(content.matches(regex)){
					String code =content.replaceAll(regex, "$1");
					handlerCommand(code, fromUserName);
					return ;
				}
				else if("人工客服".equals(content) || "人工".equals(content) || "rg".equalsIgnoreCase(content)) {
					JSONObject rs = new JSONObject();
					rs.put("MsgType","transfer_customer_service");
					rs.put("ToUserName", fromUserName);
					rs.put("FromUserName", toUserName);
					rs.put("CreateTime", DateUtils.dateline());
					logger.info(rs.toString());
					response.getWriter().print(rs.toString());

					/*Long waiterNum = XcxCsManager.appendWaiter(fromUserName);
			        if(waiterNum > 0) {
			        	JSONObject param = new JSONObject();
						JSONObject text = new JSONObject();
						param.put("msgtype", "text");
						text.put("content", "当前等待人数：" + waiterNum);
						param.put("text", text);
						autoReply(param, fromUserName);
			        }*/

					return;
				}
				else {
					/*JSONObject json = XcxCsManager.findByKeyword(content);
					if(json != null) {
						autoReply(json, fromUserName);
						return ;
					}*/
				}
			}


			/*JSONObject json = XcxCsManager.getDefault();
			if(json != null) {
				autoReply(json, fromUserName);
				return ;
			}*/
		}
	}

	/**
	 * 处理口令
	 * @param commandCode
	 */
	private void handlerCommand(String commandCode, String touser) {
		/*JSONObject command = CommandManager.get(commandCode);
		if(command != null){
			autoReply(command, touser);
			return ;
		}
		JSONObject welcome = XcxCsManager.getWelcome();
		if(welcome != null) {
			autoReply(welcome, touser);
		}*/
	}

	/**
	 * 自动回复
	 * @param param
	 * @param touser
	 */
	private void autoReply(JSONObject param, String touser) {
		AccessToken accessToken = WeixinUtils.getAccessToken(WeappUtil.APP_ID, WeappUtil.APP_SECRET);
		param.put("access_token", accessToken.getAccessToken());
		param.put("touser", touser);
		if("link".equals(param.getString("msgtype"))) {
			String url = param.getJSONObject("link").getString("url");
			url += (url.indexOf("?") > -1 ? "&" : "?") + "openid=" + touser;
			param.getJSONObject("link").put("url", url);
		}
		logger.info(param.toString());
		String content = WeixinHttpClient.post("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken.getAccessToken(), param);
		logger.info(content);
	}

	/**
	 * 消息推送
	 * @param appId
	 * @param signature
	 * @param timestamp
	 * @param nonce
	 * @param echostr
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/{appId}/pusher")
	public void pusher(
			@PathVariable("appId") String appId,
			@RequestParam("signature") String signature,
			@RequestParam("timestamp") String timestamp,
			@RequestParam("nonce") String nonce,
			@RequestParam("echostr") String echostr,
			HttpServletResponse response)throws Exception {

	}

	/**
	 * 小程序表单ID
	 * @param formId
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/formId/{formId}", method = RequestMethod.POST)
	public void appendFormId(
			@PathVariable("formId") String formId,
			HttpServletResponse response)throws Exception {
		Long userId = UserUtils.getUserId(true);
		if(userId != null){
			logger.info("=== formId === : " + formId);
		}
	}

}